/*
* Copyright (C) 2020 ~ 2024 chaigec All Rights Reserved.
*
* Author:     chaigec <chaigec@163.com>
* Maintainer: chaigec <chaigec@163.com>

 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
*/

#ifndef MK_RTSP_CLIENT_H
#define MK_RTSP_CLIENT_H
#include "MkTcp/MkTcpClient.h"
#include "MkRtspAuthenticator.h"
#include "MkRtspRequest.h"
#include "MkRtspResponse.h"
#include "MkUtil/MkLock.h"
#include "MkRtp/MkRtpUtil.h"

class CMkRtpUdpServer;
class CMkRtspSubSession;
class MkApi CMkRtspClient : public CMkTcpClient
{
public:
    CMkRtspClient(CMkEvent* pEvent, CMkTimer* pTimer, MkVector<CMkRtpUdpServer*>& VecRtpUdpServer, const MkEventRemovedCallback& RemovedCb);
    virtual ~CMkRtspClient();

protected:
    Uint32 ConnectRtspUrl(const MkString& RtspUrl);
    virtual Uint32 SendDescribe();
    virtual Uint32 SendAnnounce(const MkString& StringSdp);
    virtual Uint32 SendGetParameter();
    virtual Uint32 SendOption();
    virtual Uint32 SendSetup(CMkRtspSubSession* pSubSession, const MkString& TransportMode);
    virtual Uint32 SendPause();
    virtual Uint32 SendPlay();
    virtual Uint32 SendRecord();
    virtual Uint32 SendRedirect();
    virtual Uint32 SendSetParameter();
    virtual Uint32 SendTearDown();

    virtual Uint32 OnResponseError(const MkRtspStatusCode& StatusCode);
    virtual Uint32 OnDescribeResponse(const CMkRtspRequest& RtspReq, const CMkRtspResponse& Res);
    virtual Uint32 OnAnnounceResponse(const CMkRtspResponse& Res);
    virtual Uint32 OnGetParameterResponse(const CMkRtspResponse& Res);
    virtual Uint32 OnOptionResponse(const CMkRtspResponse& Res);
    virtual Uint32 OnPauseResponse(const CMkRtspResponse& Res);
    virtual Uint32 OnPlayResponse(const CMkRtspResponse& Res);
    virtual Uint32 OnRecordResponse(const CMkRtspResponse& Res);
    virtual Uint32 OnRedirectResponse(const CMkRtspResponse& Res);
    virtual Uint32 OnSetupResponse(const CMkRtspRequest& RtspReq, const CMkRtspResponse& Res);
    virtual Uint32 OnSetParameterResponse(const CMkRtspResponse& Res);
    virtual Uint32 OnTearDownResponse(const CMkRtspResponse& Res);

    virtual Uint32 OnAuthenticator(OUT MkString& User, OUT MkString& Password, OUT BOOL& bPasswordMd5);
    virtual Uint32 OnRtpPacket(const MkCodecType& Codec, const CMkRtpPacket& RtpPacket, const MkString& Host, Uint16 Port);
    virtual Uint32 OnRtcpPacket(const CMkRtcpPacket& RtcpPacket, const MkString& Host, Uint16 Port);

    void SetPlaySession(const MkString& PlaySession) { m_PlaySession = PlaySession; }
    const MkString& GetPlaySession() const { return m_PlaySession; }
    const MkString& GetUrl() const { return m_Url; }
    const CMkRtspAuthenticator& GetAuthenticator() const { return m_Author; }
    Uint32 AddHeaderAuthorization(const MkString& Uri, const MkRtspMethod& Method, CMkRtspRequest& RtspReq);
    Uint32 SendRtspRequest(const MkString& Uri, const MkRtspMethod& Method, const MkMap<MkRtspHeaderType, MkString>& MapHeaders = MkMap<MkRtspHeaderType, MkString>(), const MkString& strBody = "");
    CMkRtpUdpServer* GetFreeRtpUdpServer() const;
protected:

private:
    Uint32 OnRecv() override;

    Uint32 GetRequestFromCSeq(Uint32 CSeq, CMkRtspRequest& RtspReq);
    BOOL IsMethodSupported(const MkRtspMethod& Method);
    Uint32 ParseRtspMessage(Uint8* pBuf, Uint32 nLen, OUT Uint32& nUsed);
    Uint32 ParseRtspFrame(Uint8* pBuf, Uint32 nLen, OUT Uint32& nUsed);
protected:
    MkUnorderedMap<Uint32, CMkRtspSubSession*>      m_MapSession;       //key mkcodec
    BOOL                                            m_bStreamTcp;
private:
    Uint32							m_CSeq;
    MkString						m_Url;
    MkVector<MkRtspMethod>			m_VecSupportMethods;
    MkMap<Uint32, CMkRtspRequest>	m_MapRequest;
    CMkRtspAuthenticator			m_Author;
    MkString						m_PlaySession;
    Uint8*                          m_pRecvBuffer;
    Uint32                          m_nRecvMaxLen;
    Uint32                          m_nRecvOffset;

    MkVector<CMkRtpUdpServer*>      m_VecRtpUdpServer;
    MkString                        m_PlayMode;

    float                           m_Scale;   //scale  720->1080  1.5
    float                           m_Speed;
};


#endif
